package com.tupu.service.impl.admin;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tupu.common.PageResult;
import com.tupu.common.Result;
import com.tupu.entity.admin.KnowledgeInfo;
import com.tupu.entity.admin.LabelInfo;
import com.tupu.entity.admin.RelationBuildingInfo;
import com.tupu.entity.admin.RelationInfo;
import com.tupu.mapper.admin.KnowledgeListMapper;
import com.tupu.mapper.admin.LabelMapper;
import com.tupu.mapper.admin.RelationBuildingMapper;
import com.tupu.mapper.admin.RelationMapper;
import com.tupu.service.admin.RelationService;
import com.tupu.util.FileUtil;
import com.tupu.util.Neo4jUtil;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class RelationServiceImpl extends ServiceImpl<RelationMapper, RelationInfo> implements RelationService {

    @Autowired(required = false)
    private KnowledgeListMapper knowledgeListMapper;

    @Autowired(required = false)
    private RelationMapper relationMapper;

    @Autowired(required = false)
    private LabelMapper labelMapper;

    @Autowired(required = false)
    private RelationBuildingMapper relationBuildingMapper;

    @Autowired(required = false)
    private Neo4jUtil neo4jUtil;

    /**
     * 导入添加关系
     *
     * @param file_path
     * @param node_id
     * @return
     * @throws IOException
     */
    @Override
    public List<List<String>> addRelationAndBuild(String file_path, Long node_id) throws IOException, URISyntaxException {
        File file = new File(file_path);
        InputStream inputStream = null;
        ClassPathResource resource = new ClassPathResource(file_path);
        inputStream = resource.getInputStream();
        FileUtils.copyInputStreamToFile(inputStream, file);
        String absolutePath = file.getAbsolutePath();

        List<List<String>> lists = null;
        try {
            lists = FileUtil.readCsv(absolutePath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException e) {
            e.printStackTrace();
        }

        //List<List<String>> lists = FileUtil.readCsv(file_path);

        List<String> proNameList = new ArrayList<>();
        List<String> startLabelList = new ArrayList<>();
        List<String> endLabelList = new ArrayList<>();

        for (List<String> s : lists) {
            startLabelList.add(s.get(0));
            endLabelList.add(s.get(1));
            proNameList.add(s.get(2));
        }
        for (int j = 0; j < lists.size(); j++) {
            //mysql插入关系
            RelationInfo relation = new RelationInfo();
            relation.setName(proNameList.get(j));
            relation.setNodeId(node_id);
            try {
                relationMapper.insert(relation);
            } catch (Exception e) {
                e.printStackTrace();
            }
            QueryWrapper<LabelInfo> startWrapper = new QueryWrapper<>();
            startWrapper.eq("label", startLabelList.get(j));
            startWrapper.eq("node_id", node_id);
            LabelInfo startLabel = labelMapper.selectOne(startWrapper);

            QueryWrapper<LabelInfo> endWrapper = new QueryWrapper<>();
            endWrapper.eq("label", endLabelList.get(j));
            endWrapper.eq("node_id", node_id);
            LabelInfo endLabel = labelMapper.selectOne(endWrapper);

            //mysql插入关系构建表
            RelationBuildingInfo buildingList = new RelationBuildingInfo();
            buildingList.setStartId(startLabel.getId());
            buildingList.setEndId(endLabel.getId());
            buildingList.setNodeId(Long.valueOf(node_id));
            QueryWrapper<RelationInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("node_id", node_id);
            queryWrapper.eq("name", proNameList.get(j));
            RelationInfo relationInfo = relationMapper.selectOne(queryWrapper);
            buildingList.setRelationId(relationInfo.getId());
            relationBuildingMapper.insert(buildingList);
        }
        return lists;
    }

    /**
     * 根据id删除关系,同时删除关系构建表，删除节点存在的关系
     *
     * @param node_id
     * @param id
     */
    @Override
    public void delRealtion(Long node_id, Integer id) {
        RelationInfo relation = relationMapper.selectById(id);
        neo4jUtil.delRelationByNodeIdAndName(node_id, relation.getName());
        relationMapper.deleteById(id);
        relationBuildingMapper.deleteByRelationId(id);
    }

    /**
     * 根据id更新关系,修改实例关系名
     *
     * @param id
     * @param name
     * @param node_id
     */
    @Override
    public void updateRelation(Long id, String name, Long node_id) {
        RelationInfo info = relationMapper.selectById(id);
        try {
            neo4jUtil.updateRelation(info.getName(), name, node_id);
        } catch (Exception e) {
            System.out.println("修改失败，错误信息：" + e.getMessage());
        }
        RelationInfo relationInfo = new RelationInfo();
        relationInfo.setId(id);
        relationInfo.setName(name);
        relationInfo.setNodeId(node_id);
        relationMapper.updateById(relationInfo);
    }

    /**
     * 构建 本体标签间关系
     *
     * @param start_id
     * @param end_id
     * @param relation_id
     * @param node_id
     * @param relation
     */
    @Override
    public String buildingRelation(Long start_id, Long end_id, Long relation_id, Long node_id, String relation) {
        RelationBuildingInfo rb = new RelationBuildingInfo();
        // 根据node_id 查询关系表一条数据,判断是否重复
        List<RelationBuildingInfo> relationBuildingInfos = relationBuildingMapper.findOneByNodeId(node_id);
        for (RelationBuildingInfo r : relationBuildingInfos) {
            Long startId = r.getStartId();
            Long endId = r.getEndId();
            Long relationId = r.getRelationId();
            if (startId.equals(start_id) && endId.equals(end_id) && relationId.equals(relation_id)) {
                return "添加失败,数据重复";
            }
        }
        if (start_id != null && end_id != null && node_id != null && relation_id != 0) {
            rb.setNodeId(node_id);
            rb.setStartId(start_id);
            rb.setEndId(end_id);
            rb.setRelationId(relation_id);
            relationBuildingMapper.insert(rb);
            return "添加成功";
        }
        if (relation_id == 0 && !relation.isEmpty()) {
            //新增关系表
            RelationInfo relationInfo = new RelationInfo();
            relationInfo.setNodeId(node_id);
            relationInfo.setName(relation);
            relationMapper.insertOne(relationInfo);
            Long id = relationMapper.findIdByName(relation);
            //新增关系构建表
            rb.setNodeId(node_id);
            rb.setStartId(start_id);
            rb.setEndId(end_id);
            rb.setRelationId(id);
            relationBuildingMapper.insert(rb);
            return "添加成功";
        }
        return null;
    }

    /**
     * 通过关系id（relation_id） 查询关系数据 分页
     *
     * @param page
     * @param size
     * @param ids
     * @return
     */
    @Override
    public PageResult<RelationBuildingInfo> pageInfo(Integer page, Integer size, List<Long> ids) {
        List<RelationBuildingInfo> list = new ArrayList<>();
        for (Long id : ids) {
            QueryWrapper<RelationBuildingInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("relation_id", id);
            queryWrapper.orderByAsc("id");
            List<RelationBuildingInfo> records = relationBuildingMapper.selectList(queryWrapper);
            for (RelationBuildingInfo rb : records) {
                rb.setStartName(labelMapper.findlabelName(rb.getStartId()));
                rb.setEndName(labelMapper.findlabelName(rb.getEndId()));
                rb.setRelationName(relationMapper.findRelationName(rb.getRelationId()));
                String listName = knowledgeListMapper.findName(rb.getNodeId());
                rb.setKnowledgeName(listName);
                list.add(rb);
            }
        }
        List<RelationBuildingInfo> relationLists = list.stream().skip((page - 1) * size).limit(size).collect(Collectors.toList());
        PageResult<RelationBuildingInfo> info = new PageResult<>();
        int total = list.size();
        info.setList(relationLists);
        info.setPage(Long.valueOf(page));
        info.setSize(Long.valueOf(size));
        info.setTotalPages((long) (total / size + (total % size != 0 ? 1 : 0)));
        info.setTotal((long) total);
        return info;
    }

    /**
     * 根据关联表id查询一条关系列表
     *
     * @param id
     * @return
     */
    @Override
    public RelationBuildingInfo findOne(Long id) {
        RelationBuildingInfo rb = relationBuildingMapper.selectById(id);
        rb.setStartName(labelMapper.findlabelName(rb.getStartId()));
        rb.setEndName(labelMapper.findlabelName(rb.getEndId()));
        rb.setRelationName(relationMapper.findRelationName(rb.getRelationId()));
        String listName = knowledgeListMapper.findName(rb.getNodeId());
        rb.setKnowledgeName(listName);
        return rb;
    }

    /**
     * 根据id编辑修改 本体间关系
     *
     * @param id
     * @param start_id
     * @param end_id
     * @param relation_id
     * @param relation
     * @param node_id
     * @return
     */
    @Override
    public String updateRelationBuilding(Long id, Long start_id, Long end_id, Long relation_id, String relation, Long node_id) {
        // 根据node_id 查询关系表一条数据,判断是否重复
        List<RelationBuildingInfo> relationBuildingInfos = relationBuildingMapper.findOneByNodeId(node_id);
        for (RelationBuildingInfo r : relationBuildingInfos) {
            Long startId = r.getStartId();
            Long endId = r.getEndId();
            Long relationId = r.getRelationId();
            if (startId.equals(start_id) && endId.equals(end_id) && relationId.equals(relation_id)) {
                return "更新失败,数据重复";
            }
        }
        RelationBuildingInfo rb = relationBuildingMapper.selectById(id);
        if (start_id != null && end_id != null && relation_id != 0 && node_id != null) {
            rb.setNodeId(node_id);
            rb.setStartId(start_id);
            rb.setEndId(end_id);
            rb.setRelationId(relation_id);
            relationBuildingMapper.updateById(rb);
            return "修改成功";
        }
        if (!relation.isEmpty() && relation_id == 0) {
            Long relationId = relationBuildingMapper.findRelationIdById(id);
            relationMapper.deleteById(relationId);
            //新增关系表
            RelationInfo relationInfo = new RelationInfo();
            relationInfo.setNodeId(node_id);
            relationInfo.setName(relation);
            relationMapper.insertOne(relationInfo);
            Long newRelationId = relationMapper.findIdByName(relation);

            //新增关系构建表
            rb.setNodeId(node_id);
            rb.setStartId(start_id);
            rb.setEndId(end_id);
            rb.setRelationId(newRelationId);
            relationBuildingMapper.updateById(rb);
            return "修改成功";
        }
        return null;
    }

    /**
     * 根据图谱node_id 查询关系表数据
     *
     * @param node_id
     * @return
     */
    @Override
    public List<RelationInfo> findRelByNodeId(Long node_id) {
        List<RelationInfo> list = relationMapper.findRelByNodeId(node_id);
        return list;
    }

    /**
     * 标签关系数据(数据不分页)
     * @param node_id
     * @return
     */
    @Override
    public List<RelationBuildingInfo> labelRelationDataManagementAll(Long node_id) {
        //通过node_id 查询关系表数据
        List<RelationInfo> relationLists = relationMapper.findRelByNodeId(node_id);
        //id升序，返回具体关系数据
        Long id = null;
        List<RelationBuildingInfo> record = new ArrayList<>();
        for (RelationInfo rela : relationLists) {
            List<RelationBuildingInfo> records;
            QueryWrapper<RelationBuildingInfo> listQueryWrapper = new QueryWrapper<>();
            id = rela.getId();
            listQueryWrapper.or().eq("relation_id", id);
            listQueryWrapper.orderByAsc("id");
            records = relationBuildingMapper.selectList(listQueryWrapper);
            KnowledgeInfo knowledgeInfo = knowledgeListMapper.selectById(node_id);
            for (RelationBuildingInfo r : records) {
                r.setStartName(labelMapper.findlabelName(r.getStartId()));
                r.setEndName(labelMapper.findlabelName(r.getEndId()));
                r.setRelationName(relationMapper.findRelationName(r.getRelationId()));
                r.setKnowledgeName(knowledgeInfo.getName());
                record.add(r);
            }
        }
        return record;
    }
}